package orbito.util;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;

public class GfxUtils {
	
	/**
	 * Draws an arrow from point a to point b onto the given graphics context.
	 * 
	 * @param g The graphics context.
	 * @param a The base of the arrow.
	 * @param b The head of the arrow.
	 * @param size The arrow head size. This is the length of the arrow head "barbes".
	 */
	public static void drawArrow(Graphics2D g, Vec2 a, Vec2 b, int size) {
		// Paint arrow shaft.
		g.drawLine((int) a.x, (int) a.y, (int) b.x, (int) b.y);
		
		// Calculate arrow head tip point.
		Vec2 line = b.sub(a);
		Vec2 left = b.add(line.normal().unit().mul(size).sub(line.unit().mul(size)));
		Vec2 right = b.add(line.normal().unit().mul(-size).sub(line.unit().mul(size)));
		
		// Paint arrow head.
		g.drawLine((int) b.x, (int) b.y, (int) left.x, (int) left.y);
		g.drawLine((int) b.x, (int) b.y, (int) right.x, (int) right.y);
	}
	
	/**
	 * Constants for drawText and drawTextWithBackground to draw text offset in different directions.
	 */
	public static final int TEXT_UP = 1, TEXT_DOWN = 2, TEXT_VCENTER = 4, 
			TEXT_LEFT = 8, TEXT_RIGHT = 16, TEXT_HCENTER = 32, 
			TEXT_UL = TEXT_UP | TEXT_LEFT, TEXT_UR = TEXT_UP | TEXT_RIGHT, 
			TEXT_DL = TEXT_DOWN | TEXT_LEFT, TEXT_DR = TEXT_DOWN | TEXT_RIGHT, 
			TEXT_CENTER = TEXT_VCENTER | TEXT_HCENTER;
	
	/**
	 * Draw text at point (x, y) offset in the given direction onto the given graphics context.
	 * 
	 * E.g., if you want to draw a string that is centered on some point, then pass TEXT_CENTER as the direction. If 
	 * you want to draw a string that is centered in the y direction, but is offset right in the x direction, then 
	 * pass TEXT_VCENTER|TEXT_RIGHT as the direction, etc.
	 * 
	 * @param g The graphics context.
	 * @param str The text string.
	 * @param x The x-position of the text.
	 * @param y The y-position of the text.
	 * @param dir The direction in which to offset the text from its position. 
	 */
	public static void drawText(Graphics2D g, String str, int x, int y, int dir) {
		// Determine where the text should be rendered.
		FontMetrics fm = g.getFontMetrics();
		int asc = fm.getAscent();
		int lead = fm.getLeading();
		int w = (int) fm.getStringBounds(str, g).getWidth();
		int h = (int) fm.getStringBounds(str, g).getHeight();
		
		// Calculate the text offset.
		int xoff = (dir & TEXT_RIGHT) == TEXT_RIGHT ? 0 : (dir & TEXT_LEFT) == TEXT_LEFT ? -w : -w/2;
		int yoff = (dir & TEXT_DOWN) == TEXT_DOWN ? 0 : (dir & TEXT_UP) == TEXT_UP ? -h : -h/2;
		
		// Render the text in place.
		g.drawString(str, x + xoff + lead, y + yoff + asc);
	}
	
	/**
	 * Draw text at point (x, y) offset in the given direction onto the given graphics context, with the 
	 * given background color.
	 * 
	 * @see {drawText}
	 * @param g The graphics context.
	 * @param str The text string.
	 * @param fgColor The foreground color.
	 * @param bgColor The background color.
	 * @param x The x-position of the text.
	 * @param y The y-position of the text.
	 * @param dir The direction in which to offset the text from its position. 
	 */
	public static void drawTextWithBackground(Graphics2D g, String str, Color fgColor, Color bgColor, int x, int y, int dir) {
		// Determine where the text should be rendered.
		FontMetrics fm = g.getFontMetrics();
		int asc = fm.getAscent();
		int lead = fm.getLeading();
		int w = fm.stringWidth(str);
		int h = fm.getAscent() + fm.getDescent();
		
		// Calculate the text offset.
		int xoff = (dir & TEXT_RIGHT) == TEXT_RIGHT ? 0 : (dir & TEXT_LEFT) == TEXT_LEFT ? -w : -w/2;
		int yoff = (dir & TEXT_DOWN) == TEXT_DOWN ? 0 : (dir & TEXT_UP) == TEXT_UP ? -h : -h/2;
		
		// Render the background.
		g.setColor(bgColor);
		g.fillRect(x+xoff, y+yoff, w, h);
		
		// Render the text in place.
		g.setColor(fgColor);
		g.drawString(str, x + xoff + lead, y + yoff + asc);
	}
}
